# realtime_websocket_server.py
import asyncio
import websockets
import json
import time
from datetime import datetime
import socket
import random
import copy

# 存储连接的客户端
clients = set()


def get_local_ip():
    """获取本机IP地址"""
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(("8.8.8.8", 80))
        ip = s.getsockname()[0]
        s.close()
        return ip
    except Exception:
        return "127.0.0.1"


def load_template_data():
    """加载模板数据"""
    try:
        with open('hg.json', 'r', encoding='utf-8') as f:
            return json.load(f)
    except FileNotFoundError:
        return create_default_template()


def create_default_template():
    """创建默认模板数据"""
    return {
        "machinesstatus": [],
        "devicetype": [],
        "devicefloor": [],
        "todayallwarn": [],
        "todayuntreatedwarn": [],
        "penlinbox": {},
        "xiaofangbox": {},
        "success": True,
        "errmsg": ""
    }


def generate_realtime_data():
    """生成实时数据"""
    # 加载模板数据
    template = load_template_data()

    # 创建数据副本
    data = copy.deepcopy(template)

    # 更新时间戳
    current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    # 更新machinesstatus中的时间
    if "machinesstatus" in data:
        for machine in data["machinesstatus"]:
            machine["offlinetime"] = current_time

    # 更新devicetype中的时间并模拟数据变化
    if "devicetype" in data:
        for device_type in data["devicetype"]:
            if "devices" in device_type:
                for device in device_type["devices"]:
                    device["monitortime"] = current_time

                    # 模拟数据值变化
                    if "mdata" in device:
                        mdata = device["mdata"]
                        # 更新数据值
                        if "datavalue" in mdata:
                            # 根据设备类型生成合理的模拟数据
                            if device_type["devicetypeno"] == "01":  # 水浸传感器
                                # 手动设置为正常状态(0)
                                mdata["datavalue"] = "0"
                            elif device_type["devicetypeno"] == "02":  # 液位仪
                                # 液位值在合理范围内手动设置
                                if "lowvalue" in device["deviceinfo"] and "highvalue" in device["deviceinfo"]:
                                    try:
                                        low = float(device["deviceinfo"]["lowvalue"])
                                        high = float(device["deviceinfo"]["highvalue"])
                                        # 手动设置为中间值
                                        value = (low + high) / 2
                                        mdata["datavalue"] = str(round(value, 2))
                                    except:
                                        mdata["datavalue"] = "0"
                            elif device_type["devicetypeno"] == "03":  # 压力传感器
                                # 压力值在合理范围内手动设置
                                if "lowvalue" in device["deviceinfo"] and "highvalue" in device["deviceinfo"]:
                                    try:
                                        low = float(device["deviceinfo"]["lowvalue"])
                                        high = float(device["deviceinfo"]["highvalue"])
                                        # 手动设置为中间值
                                        value = (low + high) / 2
                                        mdata["datavalue"] = str(round(value, 2))
                                    except:
                                        mdata["datavalue"] = "0"

    # 更新penlinbox和xiaofangbox时间，并手动设置状态
    # if "penlinbox" in data:
    #     data["penlinbox"]["monitortime"] = current_time
    #     # 手动设置喷淋柜状态为"手动"
    #     if "devicedata" in data["penlinbox"]:
    #         data["penlinbox"]["devicedata"]["AUTO_STATUS"]["status"] = "手动"
    #
    # if "xiaofangbox" in data:
    #     data["xiaofangbox"]["monitortime"] = current_time
    #     # 手动设置消火栓柜状态为"手动"
    #     if "devicedata" in data["xiaofangbox"]:
    #         data["xiaofangbox"]["devicedata"]["AUTO_STATUS"]["status"] = "手动"

    return data


async def register_client(websocket):
    """注册新客户端"""
    clients.add(websocket)
    print(f"新客户端连接: {websocket.remote_address}")
    await send_data_to_client(websocket)


async def unregister_client(websocket):
    """注销客户端"""
    clients.discard(websocket)
    print(f"客户端断开连接: {websocket.remote_address}")


async def send_data_to_client(websocket):
    """发送数据到指定客户端"""
    try:
        realtime_data = generate_realtime_data()
        await websocket.send(json.dumps(realtime_data, ensure_ascii=False))
    except websockets.exceptions.ConnectionClosed:
        pass


async def broadcast_data():
    """广播数据到所有连接的客户端"""
    if clients:
        realtime_data = generate_realtime_data()
        message = json.dumps(realtime_data, ensure_ascii=False)
        tasks = []
        for client in clients.copy():
            tasks.append(send_data_to_client(client))
        if tasks:
            await asyncio.gather(*tasks, return_exceptions=True)


async def update_and_broadcast_data():
    """在事件循环中定期更新和广播数据"""
    while True:
        try:
            await broadcast_data()
        except Exception as e:
            print(f"更新数据时出错: {e}")
        await asyncio.sleep(2)  # 每2秒更新一次


async def handle_client(websocket, path):
    """处理客户端连接"""
    await register_client(websocket)
    try:
        async for message in websocket:
            try:
                if isinstance(message, str):
                    request = json.loads(message)
                    if isinstance(request, dict) and request.get('action') == 'get_data':
                        await send_data_to_client(websocket)
            except json.JSONDecodeError:
                pass
            except Exception as e:
                print(f"处理消息时出错: {e}")
    except websockets.exceptions.ConnectionClosed:
        pass
    finally:
        await unregister_client(websocket)


async def main():
    """主函数"""
    host_ip = get_local_ip()
    update_task = asyncio.create_task(update_and_broadcast_data())
    server = await websockets.serve(handle_client, "0.0.0.0", 5678)
    print(f"WebSocket服务器启动在 ws://{host_ip}:5678")
    print("确保手机和电脑在同一WiFi网络中")
    print("按 Ctrl+C 停止服务器")

    try:
        await server.wait_closed()
    finally:
        update_task.cancel()
        try:
            await update_task
        except asyncio.CancelledError:
            pass


if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        print("\n服务器已停止")
